home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / goto.c < prev    next >
C/C++ Source or Header  |  1988-11-24  |  5KB  |  318 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2. static char rcsid[] = "$Header: goto.c,v 2.4 85/08/22 16:03:06 timo Exp $";
  3.  
  4. /*
  5.  * B editor -- Random access focus positioning.
  6.  */
  7.  
  8. #include "b.h"
  9. #include "feat.h"
  10. #include "erro.h"
  11. #include "node.h"
  12. #include "gram.h"
  13. #include "supr.h"
  14.  
  15.  
  16. extern int winheight;
  17. extern int winstart;
  18.  
  19.  
  20. #define BEFORE (-1)
  21. #define INSIDE 0
  22. #define BEYOND 1
  23.  
  24.  
  25. /*
  26.  * Random cursor positioning (e.g., with a mouse).
  27.  */
  28.  
  29. Visible bool
  30. gotocursor(ep)
  31.     environ *ep;
  32. {
  33.     int y;
  34.     int x;
  35.  
  36.     if (!sense(&y, &x))
  37.         return No;
  38. #ifdef SCROLLBAR
  39.     if (y == winheight)
  40.         return gotoscrollbar(ep, y, x);
  41. #endif SCROLLBAR
  42.     if (!backtranslate(&y, &x))
  43.         return No;
  44.     if (!gotoyx(ep, y, x))
  45.         return No;
  46.     gotofix(ep, y, x);
  47.     return Yes;
  48. }
  49.  
  50. #ifdef SCROLLBAR
  51.  
  52. /*
  53.  * Special case for goto: user pointed at some point in the scroll bar.
  54.  * Go directly to the corresponding line.
  55.  * (The scroll bar is only present when winstart == 0; it extends from
  56.  * col 0 to winheight-1 inclusive.)
  57.  */
  58.  
  59. Hidden bool
  60. gotoscrollbar(ep, y, x)
  61.     environ *ep;
  62.     int y;
  63.     int x;
  64. {
  65.     int w;
  66.  
  67.     if (winstart != 0 || x >= winheight) { /* Not within scroll bar */
  68.         error(GOTO_OUT);
  69.         return No;
  70.     }
  71.     top(&ep->focus);
  72.     ep->mode = WHOLE;
  73.     higher(ep);
  74.     w = width(tree(ep->focus));
  75.     if (w >= 0)
  76.         w = 1;
  77.     else
  78.         w = 1-w;
  79.     if (!gotoyx(ep, x * w / winheight, 0))
  80.         return No;
  81.     oneline(ep);
  82.     return Yes;
  83. }
  84.  
  85. #endif SCROLLBAR
  86.  
  87. /*
  88.  * Set the focus to the smallest node or subset surrounding
  89.  * the position (y, x).
  90.  */
  91.  
  92. Visible bool
  93. gotoyx(ep, y, x)
  94.     register environ *ep;
  95.     register int y;
  96.     register int x;
  97. {
  98.     register node n;
  99.     register string *rp;
  100.     register int i;
  101.     register int pc;
  102.  
  103.     ep->mode = WHOLE;
  104.     while ((pc = poscomp(ep->focus, y, x)) != INSIDE) {
  105.         if (!up(&ep->focus)) {
  106.             if (pc == BEFORE)
  107.                 ep->mode = ATBEGIN;
  108.             else
  109.                 ep->mode = ATEND;
  110.             higher(ep);
  111.             return No;
  112.         }
  113.     }
  114.     higher(ep);
  115.     for (;;) {
  116.         switch (poscomp(ep->focus, y, x)) {
  117.  
  118.         case BEFORE:
  119.             i = ichild(ep->focus);
  120.             n = tree(parent(ep->focus)); /* Parent's !!! */
  121.             rp = noderepr(n);
  122.             if (Fw_positive(rp[i-1])) {
  123.                 s_up(ep);
  124.                 ep->s1 = ep->s2 = 2*i - 1;
  125.                 ep->mode = SUBSET;
  126.             }
  127.             else if (left(&ep->focus))
  128.                 ep->mode = ATEND;
  129.             else
  130.                 ep->mode = ATBEGIN;
  131.             return Yes;
  132.  
  133.         case INSIDE:
  134.             n = tree(ep->focus);
  135.             if (nchildren(n) >= 1 && Type(firstchild(n)) != Tex) {
  136.                 s_down(ep);
  137.                 continue;
  138.             }
  139.             ep->mode = WHOLE;
  140.             return Yes;
  141.  
  142.         case BEYOND:
  143.             if (rite(&ep->focus))
  144.                 continue;
  145.             n = tree(parent(ep->focus)); /* Parent's !!! */
  146.             rp = noderepr(n);
  147.             i = ichild(ep->focus);
  148.             if (Fw_positive(rp[i])) {
  149.                 s_up(ep);
  150.                 ep->s1 = ep->s2 = 2*i + 1;
  151.                 ep->mode = SUBSET;
  152.             }
  153.             else
  154.                 ep->mode = ATEND;
  155.             return Yes;
  156.  
  157.         default:
  158.             Abort();
  159.             /* NOTREACHED */
  160.  
  161.         }
  162.     }
  163. }
  164.  
  165.  
  166. /*
  167.  * Deliver relative position of (y, x) with respect to focus p:
  168.  * BEFORE: (y, x) precedes focus;
  169.  * INSIDE: (y, x) contained in focus;
  170.  * EAFTER:  (y, x) follows focus.
  171.  
  172.  */
  173.  
  174. Hidden int
  175. poscomp(p, y, x)
  176.     register path p;
  177.     register int y;
  178.     register int x;
  179. {
  180.     register int ly;
  181.     register int lx;
  182.     register int w;
  183.     register string *rp;
  184.     register node n;
  185.  
  186.     ly = Ycoord(p);
  187.     lx = Xcoord(p);
  188.     if (y < ly || y == ly && (lx < 0 || x < lx))
  189.         return BEFORE;
  190.     n = tree(p);
  191.     w = width(n);
  192.     if (w < 0) {
  193.         if (y == ly) { /* Hack for position beyond end of previous line */
  194.             rp = noderepr(n);
  195.             if (Fw_negative(rp[0]))
  196.                 return BEFORE;
  197.         }
  198.         ly += -w;
  199.         lx = -1;
  200.     }
  201.     else {
  202.         if (lx >= 0)
  203.             lx += w;
  204.     }
  205.     if (y < ly || y == ly && (lx < 0 || x < lx))
  206.         return INSIDE;
  207.     return BEYOND;
  208. }
  209.  
  210.  
  211. /*
  212.  * Position focus exactly at character indicated by (y, x) if possible.
  213.  * If this is the start of something larger, position focus at largest
  214.  * object starting here.
  215.  */
  216.  
  217. Visible Procedure
  218. gotofix(ep, y, x)
  219.     environ *ep;
  220.     int y;
  221.     int x;
  222. {
  223.     int fx;
  224.     int fy;
  225.     int len;
  226.     string repr;
  227.  
  228.     switch (ep->mode) {
  229.  
  230.     case ATBEGIN:
  231.     case ATEND:
  232.         return; /* No change; the mouse pointed in the margin. */
  233.  
  234.     case SUBSET:
  235.         if (ep->s1 > 1) {
  236.             fx = Xcoord(ep->focus);
  237.             fy = Ycoord(ep->focus);
  238.             len = focoffset(ep);
  239.             if (len < 0 || fy != y)
  240.                 return;
  241.             if ((ep->s1&1) && fx + len >= x-1) {
  242.                 repr = noderepr(tree(ep->focus))[ep->s1/2];
  243.                 if ((repr && repr[0] == ' ') != (fx + len == x))
  244.                     return;
  245.             }
  246.             else if (fx + len == x)
  247.                 return;
  248.         }
  249.         ep->mode = WHOLE;
  250.         /* Fall through */
  251.     case WHOLE:
  252.         fx = Xcoord(ep->focus);
  253.         fy = Ycoord(ep->focus);
  254.         if (y != fy)
  255.             return;
  256.         if (x <= fx ) {
  257.             for (;;) {
  258.                 if (ichild(ep->focus) > 1)
  259.                     break;
  260.                 if (!up(&ep->focus))
  261.                     break;
  262.                 repr = noderepr(tree(ep->focus))[0];
  263.                 if (!Fw_zero(repr)) {
  264.                     s_down(ep);
  265.                     break;
  266.                 }
  267.                 higher(ep);
  268.             }
  269.             if (issublist(symbol(tree(ep->focus))))
  270.                 fixsublist(ep);
  271.             return;
  272.         }
  273.         fixfocus(ep, x - fx);
  274.         ritevhole(ep);
  275.         switch(ep->mode) {
  276.         case VHOLE:
  277.             len = width(tree(ep->focus));
  278.             break;
  279.         case FHOLE:
  280.             len = fwidth(noderepr(tree(ep->focus))[ep->s1/2]);
  281.             break;
  282.         default:
  283.             return;
  284.         }
  285.         if (ep->s2 < len) {
  286.             ep->mode = SUBRANGE;
  287.             ep->s3 = ep->s2;
  288.         }
  289.         return;
  290.  
  291.     default:
  292.         Abort();
  293.     }
  294. }
  295.  
  296.  
  297. /*
  298.  * Refinement for gotoyx -- don't show right sublist of something.
  299.  */
  300.  
  301. Hidden Procedure
  302. fixsublist(ep)
  303.     environ *ep;
  304. {
  305.     path pa = parent(ep->focus);
  306.     node n;
  307.  
  308.     if (!pa)
  309.         return;
  310.     n = tree(pa);
  311.     if (nchildren(n) > ichild(ep->focus))
  312.         return;
  313.     if (samelevel(symbol(n), symbol(tree(ep->focus)))) {
  314.         ep->mode = SUBLIST;
  315.         ep->s3 = 1;
  316.     }
  317. }
  318.